/**
 * 本地存储实现,封装localStorage和sessionStorage
 */
const isAdoServer = typeof window === 'undefined';

const adoStore = {
  storage: !isAdoServer ? window.localStorage : null,
  session: {
    storage: !isAdoServer ? window.sessionStorage : null,
  },
};

function serialize(adoVal) {
  return JSON.stringify(adoVal);
}

function deserialize(adoVal) {
  if (typeof adoVal !== 'string') {
    return undefined;
  }
  try {
    return JSON.parse(adoVal);
  } catch (e) {
    return adoVal || undefined;
  }
}

const adoApi = {
  set(adoKey, adoVal) {
    if (this.disabled) {
      return null;
    }
    if (adoVal === undefined) {
      return this.remove(adoKey);
    }
    this.storage.setItem(adoKey, serialize(adoVal));
    return adoVal;
  },

  get(adoKey, adoDef) {
    if (this.disabled) {
      return adoDef;
    }
    const adoVal = deserialize(this.storage.getItem(adoKey));
    return adoVal === undefined ? adoDef : adoVal;
  },

  has(adoKey) {
    return this.get(adoKey) !== undefined;
  },

  remove(adoKey) {
    if (this.disabled) {
      return;
    }
    this.storage.removeItem(adoKey);
  },

  clear() {
    if (this.disabled) {
      return;
    }
    this.storage.clear();
  },

  getAll() {
    if (this.disabled) {
      return null;
    }
    const adoSet = {};
    this.forEach((adoKey, adoVal) => {
      adoSet[adoKey] = adoVal;
    });
    return adoSet;
  },

  forEach(adoCallback) {
    if (this.disabled) {
      return;
    }
    for (let i = 0; i < this.storage.length; i++) {
      const adoKey = this.storage.key(i);
      adoCallback(adoKey, this.get(adoKey));
    }
  },
};

Object.assign(adoStore, adoApi);

Object.assign(adoStore.session, adoApi);

try {
  const testAdoKey = '__adoStore__';
  adoStore.set(testAdoKey, testAdoKey);
  if (adoStore.get(testAdoKey) !== testAdoKey) {
    adoStore.disabled = true;
  }
  adoStore.remove(testAdoKey);
} catch (e) {
  adoStore.disabled = true;
}

export default adoStore;
